using ERPBackend.Data;
using ERPBackend.Models;
using ERPBackend.Services.Interfaces;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System;

namespace ERPBackend.Services
{
    public class OtherStockInService : IOtherStockInService
    {
        private readonly ApplicationDbContext _context;
        private readonly IInventoryService _inventoryService;

        public OtherStockInService(ApplicationDbContext context, IInventoryService inventoryService)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _inventoryService = inventoryService ?? throw new ArgumentNullException(nameof(inventoryService));
        }

        public async Task<IEnumerable<OtherStockIn>> GetAllOtherStockInsAsync()
        {
            return await _context.OtherStockIns
                .Include(os => os.Warehouse)
                .Include(os => os.OtherStockInItems)
                    .ThenInclude(osii => osii.Material)
                .ToListAsync() ?? Enumerable.Empty<OtherStockIn>();
        }

        public async Task<int> GetTotalOtherStockInsAsync()
        {
            return await _context.OtherStockIns.CountAsync();
        }

        public async Task<IEnumerable<OtherStockIn>> GetOtherStockInsPagedAsync(int page, int pageSize)
        {
            int skip = (page - 1) * pageSize;
            return await _context.OtherStockIns
                .Include(os => os.Warehouse)
                .OrderByDescending(os => os.CreatedTime)
                .Skip(skip)
                .Take(pageSize)
                .ToListAsync() ?? Enumerable.Empty<OtherStockIn>();
        }

        public async Task<OtherStockIn?> GetOtherStockInByIdAsync(int id)
        {
            return await _context.OtherStockIns
                .Include(os => os.Warehouse)
                .Include(os => os.OtherStockInItems)
                    .ThenInclude(osii => osii.Material)
                .FirstOrDefaultAsync(os => os.Id == id);
        }

        public async Task<OtherStockIn?> GetOtherStockInByCodeAsync(string stockInCode)
        {
            return await _context.OtherStockIns
                .Include(os => os.Warehouse)
                .Include(os => os.OtherStockInItems)
                    .ThenInclude(osii => osii.Material)
                .FirstOrDefaultAsync(os => os.StockInCode == stockInCode);
        }

        public async Task<OtherStockIn> CreateOtherStockInAsync(OtherStockIn otherStockIn)
        {
            // 检查入库单编码是否已存在
            var existingStockIn = await _context.OtherStockIns
                .FirstOrDefaultAsync(os => os.StockInCode == otherStockIn.StockInCode);
            if (existingStockIn != null)
            {
                throw new ArgumentException("入库单编码已存在");
            }

            // 检查仓库是否存在
            var warehouse = await _context.Warehouses.FindAsync(otherStockIn.WarehouseId);
            if (warehouse == null)
            {
                throw new ArgumentException("仓库不存在");
            }

            // 设置默认状态为待审核
            otherStockIn.Status = "待审核";
            otherStockIn.CreatedTime = DateTime.Now;
            otherStockIn.UpdatedTime = DateTime.Now;

            // 计算总数量和总金额
            if (otherStockIn.OtherStockInItems != null && otherStockIn.OtherStockInItems.Any())
            {
                otherStockIn.TotalQuantity = otherStockIn.OtherStockInItems.Sum(osii => osii.StockInQuantity);
                otherStockIn.TotalAmount = otherStockIn.OtherStockInItems.Sum(osii => osii.Amount);
            }
            else
            {
                otherStockIn.TotalQuantity = 0;
                otherStockIn.TotalAmount = 0;
            }

            _context.OtherStockIns.Add(otherStockIn);
            await _context.SaveChangesAsync();
            return otherStockIn;
        }

        public async Task<bool> UpdateOtherStockInAsync(OtherStockIn otherStockIn)
        {
            // 检查入库单是否存在
            var existingStockIn = await _context.OtherStockIns.FindAsync(otherStockIn.Id);
            if (existingStockIn == null)
            {
                return false;
            }

            // 检查入库单编码是否已被其他入库单使用
            if (existingStockIn.StockInCode != otherStockIn.StockInCode &&
                await _context.OtherStockIns.AnyAsync(os => os.StockInCode == otherStockIn.StockInCode))
            {
                throw new ArgumentException("入库单编码已被使用");
            }

            // 检查仓库是否存在
            if (otherStockIn.WarehouseId != existingStockIn.WarehouseId)
            {
                var warehouse = await _context.Warehouses.FindAsync(otherStockIn.WarehouseId);
                if (warehouse == null)
                {
                    throw new ArgumentException("仓库不存在");
                }
            }

            // 更新属性
            existingStockIn.StockInCode = otherStockIn.StockInCode;
            existingStockIn.StockInType = otherStockIn.StockInType;
            existingStockIn.WarehouseId = otherStockIn.WarehouseId;
            existingStockIn.StockInDate = otherStockIn.StockInDate;
            existingStockIn.Status = otherStockIn.Status;
            existingStockIn.TotalQuantity = otherStockIn.TotalQuantity;
            existingStockIn.TotalAmount = otherStockIn.TotalAmount;
            existingStockIn.Remark = otherStockIn.Remark;
            existingStockIn.UpdatedBy = otherStockIn.UpdatedBy;
            existingStockIn.UpdatedTime = DateTime.Now;

            _context.Entry(existingStockIn).State = EntityState.Modified;
            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> DeleteOtherStockInAsync(int id)
        {
            var otherStockIn = await _context.OtherStockIns.FindAsync(id);
            if (otherStockIn == null)
            {
                return false;
            }

            // 检查是否有相关的明细
            var hasItems = await _context.OtherStockInItems
                .AnyAsync(osii => osii.OtherStockInId == id);
            if (hasItems)
            {
                // 先删除明细
                var items = await _context.OtherStockInItems
                    .Where(osii => osii.OtherStockInId == id)
                    .ToListAsync();
                _context.OtherStockInItems.RemoveRange(items);
            }

            _context.OtherStockIns.Remove(otherStockIn);
            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> ChangeOtherStockInStatusAsync(int id, string status, int? updatedBy)
        {
            var otherStockIn = await _context.OtherStockIns.FindAsync(id);
            if (otherStockIn == null)
            {
                return false;
            }

            if (updatedBy == null)
            {
                throw new ArgumentNullException(nameof(updatedBy), "更新人不能为空");
            }

            otherStockIn.Status = status;
            otherStockIn.UpdatedBy = updatedBy.Value;
            otherStockIn.UpdatedTime = DateTime.Now;

            _context.Entry(otherStockIn).State = EntityState.Modified;
            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> ApproveOtherStockInAsync(int id, int approvedBy, string? approvalRemark = null)
        {
            var otherStockIn = await _context.OtherStockIns.FindAsync(id);
            if (otherStockIn == null)
            {
                return false;
            }

            // 检查是否为待审核状态
            if (otherStockIn.Status != "待审核")
            {
                throw new ArgumentException("只有待审核状态的入库单才能进行审批");
            }

            // 更新状态和审核信息
            otherStockIn.Status = "已审核";
            otherStockIn.ApprovedBy = approvedBy;
            otherStockIn.ApprovedTime = DateTime.Now;
            otherStockIn.UpdatedBy = approvedBy;
            otherStockIn.UpdatedTime = DateTime.Now;
            if (!string.IsNullOrEmpty(approvalRemark))
            {
                otherStockIn.Remark = approvalRemark;
            }

            // 获取明细
            var items = await _context.OtherStockInItems
                .Include(osii => osii.Material)
                .Where(osii => osii.OtherStockInId == id)
                .ToListAsync();

            // 更新库存
            foreach (var item in items)
            {
                await _inventoryService.UpdateInventoryQuantityAsync(
                    item.MaterialId,
                    otherStockIn.WarehouseId,
                    item.StockInQuantity,
                    (byte)0, // 操作类型，假设0表示入库
                    "其他入库",
                    approvedBy
                );
            }

            _context.Entry(otherStockIn).State = EntityState.Modified;
            return await _context.SaveChangesAsync() > 0;
        }
    }
}